package com.orangecy.common.cyioc;

import com.orangecy.common.anno.CyAutowired;
import com.orangecy.common.exception.OrangeCyException;

import java.lang.reflect.Field;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author : orangeCy.奕
 * @Product : 猎豹养成产品源码
 * @Time : 2021/10/27
 * @Desc : 8点33分开始
 */
public class CyCommonContainer implements CyContainer {

    /**
     * 维护容器内bean对象映射map
     * key:xxxClass value:对象
     */
    private Map<String,Object> beanNameMap;

    /**
     * 冗余keyName 方便操作
     */
    private Map<String,String> beanKeyMap;

    public CyCommonContainer(){
        this.beanNameMap = new ConcurrentHashMap<>();
        this.beanKeyMap = new ConcurrentHashMap<>();
    }

    /**
     * 根据class类型获取其范型T
     * @param clazz
     * @param <T>
     * @return
     */
    @Override
    public <T> T getBean(Class<T> clazz) {
        String name = clazz.getName();
        Object o = beanNameMap.get(name);
        return Objects.isNull(o) ? null : (T)o ;
    }

    @Override
    public void initCyContainer() {
        beanNameMap.forEach((k,v) -> {
            //拿到v所有字段
            Field[] fields = v.getClass().getDeclaredFields();
            for(Field f : fields) {
                //判断此属性上是否打上注解
                CyAutowired annotation = f.getAnnotation(CyAutowired.class);
                if(Objects.nonNull(annotation)) {
                    //提炼出来
                    Object autoWiredField = null;
                    //如果存在 开始注入 获取注解的bean名称
                    String name = annotation.name();
                    if(!"".equals(name)) {
                        String className = beanKeyMap.get(name);
                        if(Objects.nonNull(className) && !Objects.equals(className,"")) {
                            //从初始化容器维护map映射取
                            autoWiredField = beanNameMap.get(className);
                        }
                        //如果说不存在 肯定是异常case
                        if(null == autoWiredField) {
                            throw new OrangeCyException("不存在beanKey");
                        }
                    }else{
                        //注解上没有指定name属性
                        Class<?> value = annotation.value();
                        //如果和默认的正好匹配符合
                        if(Objects.equals(annotation.value(),Class.class)) {
                            autoWiredField = registerBean(f.getType());
                        }else {
                            //找到指定的那个bean
                            Object bean = getBean(annotation.value());
                            if(Objects.isNull(bean)) {
                                autoWiredField = registerBean(f.getType());
                            }
                        }
                    }
                    if(null == autoWiredField) {
                        throw new OrangeCyException("error");
                    }
                    boolean accessible = f.isAccessible();
                    f.setAccessible(true);
                    try {
                        f.set(v,autoWiredField);
                        f.setAccessible(accessible);
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
    }

    @Override
    public Object registerBean(Class<?> clazz) {
        String name = clazz.getName();
        beanKeyMap.put(name,name);
        //生成实例
        Object instance = null;
        try {
            instance = clazz.newInstance();
            beanNameMap.put(name, instance);
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return instance;
    }
}